import dayjs from 'dayjs';
import {gridLayout} from './layoutUtils';
import {uuid} from './utils';
import {pushStack} from "./undoRedoUtil";
import {clone, deepMix} from '@antv/util/lib';

/*
* 节点：组合和拆分
* 组合完也是一个点，只是属性里面包含该组所有点信息
*  */
/**
 * 组合
 *
 * @param item []
 */
export const groupNodes = (graph, items) => {
    // 校验，并处理哪些能合并
    // 根据edge相同（数量 属性 source），进行分组
    let groups = groupBy(items, function (item) {
        let itemModel = item.getModel();
        let itemEdges = item.getEdges();
        let sourceNode = {};
        let targetNode = {};
        let itemEdgeIds = [];
        itemEdges.forEach(edge => {
            sourceNode = edge.getSource();
            targetNode = edge.getTarget();
            if (sourceNode.getID() === itemModel.id) {
                itemEdgeIds.push(targetNode.getID());
            }
            if (targetNode.getID() === itemModel.id) {
                itemEdgeIds.push(sourceNode.getID());
            }
        })

        // itemEdgeIds 排序
        itemEdgeIds = itemEdgeIds.sort();
        // console.log(itemEdgeIds)
        // console.log(itemEdgeIds)
        return item.getEdges().length + JSON.stringify(itemEdgeIds);
    })

    // console.log(groups)
    // group_唯一ID，如果两次入库ID相同，则合并
    let actionType = 'group_' + uuid();
    groups.forEach(items => {
        // 分组后单个点不合并
        if (items.length > 1) {
            // 移动的目标点位
            let targetPosition = {
                x: items[0].get('model').x,
                y: items[0].get('model').y
            };

            updateGroup(graph, items, targetPosition, actionType);
        }
    })
}

/**
 * 拆分
 *
 * @param groupItem {
 *     item: {},
 *     exportItems: {}
 * }
 */
export const unGroupNodes = (graph, groupItems) => {
    // console.log(groupItems)
    // node 切换为正常点
    // edge source/target 切换
    let before = {
        nodes: [],
        combos: [],
        edges: [],
        groups: []
    };
    let after = {
        nodes: [],
        combos: [],
        edges: [],
        groups: []
    };
    let actionType = 'group_' + uuid();
    groupItems.forEach(item => {
        let nodes = item.getModel().nodes;
        let groupId = item.getModel().id;
        let edges = item.getEdges();
        let newEdges = [];

        if (nodes) {
            // 展开前
            before.nodes.push(clone(item.getModel()));

            let sourceNode = {};
            let targetNode = {};
            let singleEdge = {};
            let newSourceIds = [];
            edges.forEach(edge => {
                sourceNode = edge.getSource();
                targetNode = edge.getTarget();

                before.edges.push(clone(edge.getModel()));
                newSourceIds.push(sourceNode.getID() === groupId ? targetNode.getID() : sourceNode.getID());
            })

            nodes.forEach(node => {
                let nodeItem = graph.addItem('node', node, false);
                after.nodes.push(nodeItem.getModel());
                graph.setItemState(nodeItem, 'selected', true);

                newSourceIds.forEach(sourceId => {
                    singleEdge = {
                        source: sourceId,
                        target: node.id,
                    }
                    // console.log(singleEdge)

                    let addEdges = graph.addItem('edge', singleEdge, false);
                    after.edges.push(addEdges.getModel());
                })
            })

            graph.removeItem(item, false);

            gridLayout(graph, nodes, newEdges);

            pushStack(graph, actionType, before, after);
        }
    })
}

/**
 * 更新节点
 * @param item 待更新节点实例
 * @param evt
 */
function updateGroup(graph, items, targetPosition, actionType) {
    let before = {
        nodes: [],
        combos: [],
        edges: [],
        groups: []
    };
    let after = {
        nodes: [],
        combos: [],
        edges: [],
        groups: []
    };

    // 记录节点基本信息
    let nodes = [];
    let edges = [];
    let nodeId = '';
    items.forEach((item, index) => {
        if (index === 0) {
            nodeId = item.getModel().id;
            edges = item.getEdges();
        }
        nodes.push(item.getModel());
        before.nodes.push(clone(item.getModel()))
        item.getEdges().forEach(edge => {
            before.edges.push(clone(edge.getModel()));
        })
    })

    // 移动动画
    graph.get('canvas').animate((ratio) => {
        items.forEach(item => {
            // 设置目标点
            const itemModel = item.get('model');
            let sX = itemModel.x;
            let sY = itemModel.y;
            let tX = targetPosition.x;
            let tY = targetPosition.y;

            let m = sX + (tX - sX) * ratio;
            let n = sY + (tY - sY) * ratio;
            let pos = {
                x: m,
                y: n
            }
            // console.log(pos)
            graph.update(item, pos, false)
        })
    }, {
        duration: '300',
        easing: "easeLinear",
        callback: function () {
            // node 切换为组合点,时间戳dayjs().valueOf()
            let groupId = "group_" + dayjs().valueOf();
            let groupNode = {
                id: groupId, // 先写死
                label: groupId, // 先写死
                size: [40, 40],
                type: "person-node",
                nodes: nodes,
                x: targetPosition.x,
                y: targetPosition.y
            }

            let groupItem = graph.addItem('node', groupNode, false);
            after.nodes.push(groupItem.getModel());
            graph.setItemState(groupItem, 'selected', true);

            // edge
            let sourceNode = {};
            let targetNode = {};
            let groupEdge = {};
            let newSourceId = '';
            edges.forEach((edge, index) => {
                sourceNode = edge.getSource();
                targetNode = edge.getTarget();
                newSourceId = sourceNode.getID() === nodeId ? targetNode.getID() : sourceNode.getID();

                groupEdge = {
                    source: newSourceId,
                    target: groupId,
                }

                let addEdges = graph.addItem('edge', groupEdge, false);
                after.edges.push(addEdges.getModel());
            })

            // 删除节点
            items.forEach((item, index) => {
                graph.removeItem(item, false);
            })

            pushStack(graph, actionType, before, after);
        }
    })
}

/**
 * 分组方法
 *
 * @param array
 * @param f
 * @returns {*[]}
 */
function groupBy(array, f) {
    let groups = {};
    array.forEach(function (o) {
        let group = JSON.stringify(f(o));
        groups[group] = groups[group] || [];
        groups[group].push(o);
    });
    return Object.keys(groups).map(function (group) {
        return groups[group];
    });
}
